/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package explorer;

import compare.CompareUnited;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.poi.hwpf.extractor.WordExtractor;
import server.ServletUnited;

/**
 *
 * @author user1
 */
public final class ExplorerUnited {
    
    public static int modeExplore = 0;
        public static final int EXPLORE_DFS = 0;
        public static final int EXPLORE_BFS = 1;
        
    public static int modeSearch = 0;
        public static final int SEARCH_BRUTEFORCE = 0;
        public static final int SEARCH_KMP = 1;
        public static final int SEARCH_BOYERMOORE = 2;
    
    public static File startDir;
    public static ArrayList<FileUnited> result = new ArrayList<FileUnited>();
    public static String[] kataSambung = {"yang","di","ke","dari","dan","dengan","atau","sejak","jika",
            "andaikan","agar","biarpun","ibarat","karena","sehingga","tanpa","bahwa","bagi","untuk",
            "sebab","sambil","beserta","bersama","oleh","pada","hingga","sampai","sejak","semenjak",
            "tentang"};
    
    public static long time = 0;

    public static void setExplore(int e) {
        modeExplore = e;
    }
    
    public static void setSearch(int s) {
        modeSearch = s;
    }
    
    public static void setDir(String[] dir) throws FileNotFoundException {
        startDir = new File(dir[0]);
    }
    
    
    private static List<File> exploreDFS(File dir, String pattern) throws FileNotFoundException {
        List<File> list = new ArrayList<File>();
        File[] subdir = dir.listFiles();
        FileUnited fileUnited;
        List<File> fileDir = Arrays.asList(subdir);
        StringTokenizer frase;
        File f;
        int pass = 0;
        //for (File f : fileDir) {
        while (pass < fileDir.size()) {
            f = fileDir.get(pass);
            //list.add(f);
            if (!f.isFile()) {
                List<File> deeperList = exploreDFS(f, pattern);
                list.addAll(deeperList);
            } else if (FileUnited.fileValidator(f)) {
                fileUnited = new FileUnited(f);
                frase = new StringTokenizer(pattern);
                inspectToken(frase, fileUnited);
                ServletUnited.f = f;
            }
            ++pass;
        }
        return list;
    }
    
    private static void exploreBFS(File dir, String pattern) throws FileNotFoundException {
        List<File> list = new ArrayList<File>();
        File[] subdir = dir.listFiles();
        FileUnited fileUnited;
        List<File> fileDir = Arrays.asList(subdir);
        StringTokenizer frase;
        File f;
        int pass = 0;
        list.addAll(fileDir);
        //for (File f : fileDir) {
        while (pass < list.size()) {
            f = list.get(pass);
            //list.add(f);
            if (!f.isFile()) {
                subdir = f.listFiles();
                List<File> deeperList = Arrays.asList(subdir);
                list.addAll(deeperList);
            } else if (FileUnited.fileValidator(f)) {
                fileUnited = new FileUnited(f);
                frase = new StringTokenizer(pattern);
                inspectToken(frase, fileUnited);
                ServletUnited.f = f;
            }
            ++pass;
        }
    }
    
    public static void inspectToken(StringTokenizer frase, FileUnited fileUnited) {
        String token;
        boolean found = false;
        int startjudul = -1;
        int i, startchar = -1;
        String name = fileUnited.getName().toLowerCase();
        String content = fileUnited.getContent().toLowerCase();
        while (frase.hasMoreTokens()) {
            token = frase.nextToken().toLowerCase();
            if (!filter(token)) {
                switch (modeSearch) {
                    case SEARCH_BRUTEFORCE:
                        startjudul = CompareUnited.compareBruteForce(token,name);
                        startchar = CompareUnited.compareBruteForce(token,content);
                    break;
                    case SEARCH_KMP:
                        startjudul = CompareUnited.compareKMP(token,name);
                        startchar = CompareUnited.compareKMP(token,content);
                    break;
                    case SEARCH_BOYERMOORE:
                        startjudul = CompareUnited.compareBoyerMoore(token,name);
                        startchar = CompareUnited.compareBoyerMoore(token,content);
                    break;
                    default:
                    break;
                }
                i = 0;
                if (startjudul >= 0 || (startchar != CompareUnited.NOT_FOUND)) {
                    found = false;
                    while(!found && i < result.size()) {
                            if (result.get(i).getName().equals(fileUnited.getName()) && result.get(i).getExtension().equals(fileUnited.getExtension())) {
                                found = true;
                            } else {
                                i++;
                            }
                        }
                    if (!found) {
                        result.add(new FileUnited(fileUnited));
                        if (startjudul != CompareUnited.NOT_FOUND) {
                            result.get(result.size()-1).setStartJudul(startjudul);
                            result.get(result.size()-1).setTokenJudul(token.length());
                        }
                        if (startchar != CompareUnited.NOT_FOUND) {
                            result.get(result.size()-1).setStartChar(startchar);
                            result.get(result.size()-1).setTokenLength(token.length());
                        }
                        startchar=-1;
                    } else {
                        if (startjudul != CompareUnited.NOT_FOUND) {
                            result.get(result.size()-1).setStartJudul(startjudul);
                            result.get(result.size()-1).setTokenJudul(token.length());
                        }
                        if (startchar != CompareUnited.NOT_FOUND) {
                            result.get(i).setStartChar(startchar);
                            result.get(i).setTokenLength(token.length());
                        }
                        startchar=-1;
                    }
                }
            }
        }
    }

    public static void startExplore(String[] pattern) throws FileNotFoundException {
        validateDirectory(startDir);
        long timeStart = System.nanoTime();
        result.clear();
        switch (modeExplore) {
            case EXPLORE_DFS:
                exploreDFS(startDir, pattern[0]);
                break;
            case EXPLORE_BFS:
                exploreBFS(startDir, pattern[0]);
                break;
            default:
                break;
        }
        long timeStop = System.nanoTime();
        time = timeStop - timeStart;
    }
    

    /**
     * Directory is valid if it exists, does not represent a file, and can be read.
     */
    static private void validateDirectory(File dir) throws FileNotFoundException {
        if (dir == null) {
            throw new IllegalArgumentException("Directory should not be null.");
        }
        if (!dir.exists()) {
            throw new FileNotFoundException("Directory does not exist: " + dir);
        }
        if (!dir.isDirectory()) {
            throw new IllegalArgumentException("Is not a directory: " + dir);
        }
        if (!dir.canRead()) {
            throw new IllegalArgumentException("Directory cannot be read: " + dir);
        }
    }
    
    public static boolean filter(String token) {
        boolean found = false;
        int i = 0;
        while (!found && i < kataSambung.length) {
            if (token.equals(kataSambung[i])) {
                found = true;
            } else {
                i++;
            }
        }
        return found;
    }
}
